using System;
using System.Collections.Generic; // Added for List
using System.Linq; // Added for Select

namespace WenYu.Runtime
{
    /// <summary>
    /// 运行时值 - 封装所有可能的数据类型
    /// 
    /// 功能:
    /// - 统一表示整型、实型、文字、真假值
    /// - 类型转换(如数值→文字)
    /// - 类型检查和强制转换
    /// 
    /// 对标需求: REQ-05 标准库接口
    /// </summary>
    public class Value
    {
        /// <summary>值的类型</summary>
        public enum ValueType
        {
            Integer,    // 整型
            Float,      // 实型
            String,     // 文字
            Boolean,    // 真假
            Array,      // 数组
            Object,     // 对象 (P4新增)
            Null        // null值(预留)
        }

        /// <summary>当前值的类型</summary>
        public ValueType Type { get; private set; }

        /// <summary>内部存储的值</summary>
        private object? _value;

        // ===== 构造函数 =====

        /// <summary>创建整数值</summary>
        public Value(int intValue)
        {
            Type = ValueType.Integer;
            _value = intValue;
        }

        /// <summary>创建实数值</summary>
        public Value(double floatValue)
        {
            Type = ValueType.Float;
            _value = floatValue;
        }

        /// <summary>创建字符串值</summary>
        public Value(string stringValue)
        {
            Type = ValueType.String;
            _value = stringValue ?? string.Empty;
        }

        /// <summary>创建布尔值</summary>
        public Value(bool boolValue)
        {
            Type = ValueType.Boolean;
            _value = boolValue;
        }

        /// <summary>创建null值(预留)</summary>
        private Value()
        {
            Type = ValueType.Null;
            _value = null;
        }

        /// <summary>创建数组值</summary>
        public Value(List<Value> arrayValue)
        {
            Type = ValueType.Array;
            _value = arrayValue ?? new List<Value>();
        }

        /// <summary>创建对象值</summary>
        public Value(Dictionary<string, Value> objectFields, string className)
        {
            Type = ValueType.Object;
            _value = objectFields ?? new Dictionary<string, Value>();
            _className = className;
        }

        /// <summary>对象的类名（仅用于Object类型）</summary>
        private string? _className;

        // ===== 类型检查 =====

        /// <summary>是否为整数</summary>
        public bool IsInteger => Type == ValueType.Integer;

        /// <summary>是否为实数</summary>
        public bool IsFloat => Type == ValueType.Float;

        /// <summary>是否为字符串</summary>
        public bool IsString => Type == ValueType.String;

        /// <summary>是否为布尔</summary>
        public bool IsBoolean => Type == ValueType.Boolean;

        /// <summary>是否为数值(整数或实数)</summary>
        public bool IsNumeric => Type == ValueType.Integer || Type == ValueType.Float;

        /// <summary>是否为数组</summary>
        public bool IsArray => Type == ValueType.Array;

        /// <summary>是否为对象</summary>
        public bool IsObject => Type == ValueType.Object;

        // ===== 值获取(带类型检查) =====

        /// <summary>获取整数值，类型不匹配时抛出异常</summary>
        /// <exception cref="InvalidOperationException">类型不匹配</exception>
        public int AsInteger()
        {
            if (Type != ValueType.Integer)
                throw new InvalidOperationException($"无法将 {Type} 转换为整型");
            return (int)_value!;
        }

        /// <summary>获取实数值，类型不匹配时抛出异常</summary>
        /// <exception cref="InvalidOperationException">类型不匹配</exception>
        public double AsFloat()
        {
            if (Type != ValueType.Float)
                throw new InvalidOperationException($"无法将 {Type} 转换为实型");
            return (double)_value!;
        }

        /// <summary>获取字符串值，类型不匹配时抛出异常</summary>
        /// <exception cref="InvalidOperationException">类型不匹配</exception>
        public string AsString()
        {
            if (Type != ValueType.String)
                throw new InvalidOperationException($"无法将 {Type} 转换为文字");
            return (string)_value!;
        }

        /// <summary>获取布尔值，类型不匹配时抛出异常</summary>
        /// <exception cref="InvalidOperationException">类型不匹配</exception>
        public bool AsBoolean()
        {
            if (Type != ValueType.Boolean)
                throw new InvalidOperationException($"无法将 {Type} 转换为真假");
            return (bool)_value!;
        }

        /// <summary>获取数组值，类型不匹配时抛出异常</summary>
        /// <exception cref="InvalidOperationException">类型不匹配</exception>
        public List<Value> AsArray()
        {
            if (Type != ValueType.Array)
                throw new InvalidOperationException($"无法将 {Type} 转换为数组");
            return (List<Value>)_value!;
        }

        /// <summary>获取数组长度</summary>
        public int GetArrayLength()
        {
            if (Type != ValueType.Array)
                throw new InvalidOperationException($"无法获取 {Type} 的长度");
            return ((List<Value>)_value!).Count;
        }

        /// <summary>获取数组元素</summary>
        public Value GetArrayElement(int index)
        {
            if (Type != ValueType.Array)
                throw new InvalidOperationException($"无法访问 {Type} 的元素");
            var arr = (List<Value>)_value!;
            if (index < 0 || index >= arr.Count)
                throw new IndexOutOfRangeException($"数组索引超出范围: {index}，数组大小: {arr.Count}");
            return arr[index];
        }

        /// <summary>设置数组元素</summary>
        public void SetArrayElement(int index, Value value)
        {
            if (Type != ValueType.Array)
                throw new InvalidOperationException($"无法修改 {Type} 的元素");
            var arr = (List<Value>)_value!;
            if (index < 0 || index >= arr.Count)
                throw new IndexOutOfRangeException($"数组索引超出范围: {index}，数组大小: {arr.Count}");
            arr[index] = value;
        }

        // ===== 对象操作 (P4新增) =====

        /// <summary>获取对象字段字典</summary>
        public Dictionary<string, Value> AsObject()
        {
            if (Type != ValueType.Object)
                throw new InvalidOperationException($"无法将 {Type} 转换为对象");
            return (Dictionary<string, Value>)_value!;
        }

        /// <summary>获取对象的类名</summary>
        public string GetClassName()
        {
            if (Type != ValueType.Object)
                throw new InvalidOperationException($"无法获取 {Type} 的类名");
            return _className ?? "未知类";
        }

        /// <summary>获取对象字段值</summary>
        public Value GetField(string fieldName)
        {
            if (Type != ValueType.Object)
                throw new InvalidOperationException($"无法访问 {Type} 的字段");
            var obj = (Dictionary<string, Value>)_value!;
            if (!obj.ContainsKey(fieldName))
                throw new KeyNotFoundException($"对象中不存在字段: {fieldName}");
            return obj[fieldName];
        }

        /// <summary>设置对象字段值</summary>
        public void SetField(string fieldName, Value value)
        {
            if (Type != ValueType.Object)
                throw new InvalidOperationException($"无法修改 {Type} 的字段");
            var obj = (Dictionary<string, Value>)_value!;
            obj[fieldName] = value;
        }

        /// <summary>检查对象是否有指定字段</summary>
        public bool HasField(string fieldName)
        {
            if (Type != ValueType.Object)
                return false;
            var obj = (Dictionary<string, Value>)_value!;
            return obj.ContainsKey(fieldName);
        }

        // ===== 隐式类型转换 =====

        /// <summary>转换为字符串(用于输出)</summary>
        public override string ToString()
        {
            return Type switch
            {
                ValueType.Integer => ((int)_value!).ToString(),
                ValueType.Float => ((double)_value!).ToString("G"),  // G格式避免尾部零
                ValueType.String => (string)_value!,
                ValueType.Boolean => (bool)_value! ? "真真" : "假假",
                ValueType.Array => FormatArray(),
                ValueType.Object => FormatObject(),
                _ => "null"
            };
        }

        /// <summary>格式化数组为字符串</summary>
        private string FormatArray()
        {
            var arr = (List<Value>)_value!;
            var elements = string.Join("，", arr.Select(v => v.ToString()));
            return $"【{elements}】";
        }

        /// <summary>格式化对象为字符串</summary>
        private string FormatObject()
        {
            var obj = (Dictionary<string, Value>)_value!;
            var fields = string.Join("，", obj.Select(kvp => $"{kvp.Key}={kvp.Value.ToString()}"));
            return $"{_className}({fields})";
        }

        /// <summary>转换为布尔值(用于条件判断)</summary>
        public bool ToBoolean()
        {
            return Type switch
            {
                ValueType.Boolean => (bool)_value!,
                ValueType.Integer => ((int)_value!) != 0,
                ValueType.Float => Math.Abs((double)_value!) > double.Epsilon,
                ValueType.String => ((string)_value!).Length > 0,
                ValueType.Array => ((List<Value>)_value!).Count > 0,  // 非空数组为真
                ValueType.Object => true,  // 对象总是为真
                _ => false
            };
        }

        /// <summary>转换为数值(用于算术运算)</summary>
        /// <returns>整数返回int，实数返回double</returns>
        /// <exception cref="InvalidOperationException">无法转换为数值</exception>
        public object ToNumeric()
        {
            if (!IsNumeric)
                throw new InvalidOperationException($"无法将 {Type} 转换为数值");
            
            return Type switch
            {
                ValueType.Integer => AsInteger(),
                ValueType.Float => AsFloat(),
                _ => throw new InvalidOperationException("不应该到达此处")
            };
        }

        // ===== 运算操作符 =====

        /// <summary>两个值是否相等</summary>
        public static bool operator ==(Value? left, Value? right)
        {
            // null处理
            if (left is null && right is null) return true;
            if (left is null || right is null) return false;

            // 相同类型直接比较
            if (left.Type == right.Type)
            {
                return left.Type switch
                {
                    ValueType.Integer => left.AsInteger() == right.AsInteger(),
                    ValueType.Float => Math.Abs(left.AsFloat() - right.AsFloat()) < double.Epsilon,
                    ValueType.String => left.AsString() == right.AsString(),
                    ValueType.Boolean => left.AsBoolean() == right.AsBoolean(),
                    _ => false
                };
            }

            // 不同类型转换比较
            if (left.IsNumeric && right.IsNumeric)
            {
                double l = left.Type == ValueType.Integer ? left.AsInteger() : left.AsFloat();
                double r = right.Type == ValueType.Integer ? right.AsInteger() : right.AsFloat();
                return Math.Abs(l - r) < double.Epsilon;
            }

            return false;
        }

        /// <summary>两个值是否不相等</summary>
        public static bool operator !=(Value? left, Value? right)
        {
            return !(left == right);
        }

        /// <summary>覆盖Equals方法</summary>
        public override bool Equals(object? obj)
        {
            return this == (obj as Value);
        }

        /// <summary>覆盖GetHashCode方法</summary>
        public override int GetHashCode()
        {
            return Type switch
            {
                ValueType.Integer => AsInteger().GetHashCode(),
                ValueType.Float => AsFloat().GetHashCode(),
                ValueType.String => AsString().GetHashCode(),
                ValueType.Boolean => AsBoolean().GetHashCode(),
                ValueType.Array => _value!.GetHashCode(),  // 数组使用引用哈希
                ValueType.Object => _value!.GetHashCode(),  // 对象使用引用哈希
                _ => 0
            };
        }

        // ===== 工厂方法 =====

        /// <summary>创建null值</summary>
        public static Value Null => new();

        /// <summary>从对象创建Value</summary>
        /// <exception cref="ArgumentException">不支持的类型</exception>
        public static Value FromObject(object obj)
        {
            return obj switch
            {
                int i => new Value(i),
                double d => new Value(d),
                string s => new Value(s),
                bool b => new Value(b),
                null => Null,
                _ => throw new ArgumentException($"不支持的类型: {obj.GetType().Name}")
            };
        }

        /// <summary>调试输出</summary>
        public string DebugInfo => $"Value({Type}: {ToString()})";
    }
}
